#include "circleedgefitting.h"

CircleEdgeFitting::CircleEdgeFitting()
{

}

bool CircleEdgeFitting::PR_Circle_Edge_Fitting(QImage image, QImage &resultImage, QString prName, PRResultStruct &prResult, QVariantMap args,
                                               PRResultImageInfo &prResultImageInfo)
{
    qInfo("PR_Circle_Edge_Fitting");

    atl::String g_constData3;

    atl::String g_constData5;

    atl::String g_constData7;

    QString grayModelFilename = prName;
    QString circleFittingFieldFilename = prName;
    QString regionFilename = prName;

    grayModelFilename.replace("_circleFittingModel", "_grayModel");
    regionFilename.replace("_circleFittingModel", "_region");

    //g_constData2 = L".//prConfig//test_region.avdata";

    g_constData3 = L"Region";

    //g_constData4 = L".//prConfig//test_grayModel.avdata";

    g_constData5 = L"GrayModel?";

    //g_constData6 = L".//prConfig//test_circleFittingModel.avdata";

    g_constData7 = L"CircleFittingField";

    avl::Image image1;
    avl::Region region1;
    atl::Conditional< avl::GrayModel > grayModel1;
    avs::FitCircleToEdgesState fitCircleToEdgesState1;
    avl::Image image2;
    avl::Image image3;

    try {
        if (image.depth() != 8)
            image = image.convertToFormat(QImage::Format_RGB888);
        avl::Image imageInput(image.width(), image.height(), image.bytesPerLine(), avl::PlainType::Type::UInt8, image.depth()/8, image.bits());
        avl::RealignImagePitch(imageInput, image1);

        avl::CircleFittingField circleFittingField1;
        atl::Conditional< avl::Circle2D > circle2D1;
        atl::Conditional< avl::Point2D > point2D1;

        avs::LoadObject< avl::Region >( regionFilename.toStdString().c_str(), avl::StreamMode::Binary, g_constData3, region1 );
        avs::LoadObject< atl::Conditional< avl::GrayModel > >( grayModelFilename.toStdString().c_str(), avl::StreamMode::Binary, g_constData5, grayModel1 );
        avs::LoadObject< avl::CircleFittingField >( circleFittingFieldFilename.toStdString().c_str(), avl::StreamMode::Binary, g_constData7, circleFittingField1 );

        if (grayModel1 != atl::NIL)
        {
            atl::Conditional< avl::Object2D > object2D1;

            avl::LocateSingleObject_NCC( image1, region1, grayModel1.Get(), 3, 3, false, 0.5f, object2D1, atl::NIL, atl::Dummy< atl::Array< avl::Image > >().Get(), atl::Dummy< atl::Array< avl::Image > >().Get(), atl::Dummy< atl::Conditional< atl::Array< float > > >().Get() );

            if (object2D1 != atl::NIL)
            {
                avl::Point2D point2D2;
                avl::CoordinateSystem2D coordinateSystem2D1;

                point2D2 = object2D1.Get().Point();
                avl::CreateCoordinateSystemFromPoint( point2D2, 0.0f, 1.0f, 1.0f, coordinateSystem2D1 );

                // Function AvsFilter_FitCircleToEdges is intended for generated code only. Consider use of CreateFittingMap and FitCircleToEdges functions in regular programs.
                avs::AvsFilter_FitCircleToEdges( fitCircleToEdgesState1, image1, circleFittingField1, coordinateSystem2D1, 10, 5, avl::InterpolationMethod::Bilinear, avl::EdgeScanParams(avl::ProfileInterpolationMethod::Quadratic4, 1.0f, 5.0f, avl::EdgeTransition::Any), avl::Selection::Best, atl::NIL, 0.1f, avl::CircleFittingMethod::AlgebraicTaubin, atl::NIL, circle2D1, atl::NIL, atl::NIL, atl::NIL, atl::Dummy< atl::Array< avl::Segment2D > >().Get(), atl::Dummy< atl::Array< avl::Rectangle2D > >().Get(), atl::Dummy< atl::Array< avl::Profile > >().Get(), atl::Dummy< atl::Array< avl::Profile > >().Get() );

                if (circle2D1 != atl::NIL)
                {
                    point2D1.AssignNonNil();

                    point2D1.Get() = circle2D1.Get().Center();
                }
                else
                {
                    point2D1 = atl::NIL;
                    qWarning("Cannot find the circle edge");
                    return false;
                }
            }
            else
            {
                circle2D1 = atl::NIL;
                point2D1 = atl::NIL;

                qWarning("Cannot find the target model");
                return false;
            }
        }
        else
        {
            circle2D1 = atl::NIL;
            point2D1 = atl::NIL;
            qWarning("Cannot find the gray model input");
            return false;
        }

        prResult.x = circle2D1.Get().Center().X();
        prResult.y = circle2D1.Get().Center().Y();

        prResult.ori_x = circle2D1.Get().Center().X();
        prResult.ori_y = circle2D1.Get().Center().Y();

        prResultImageInfo.result_x = prResult.x;
        prResultImageInfo.result_y = prResult.y;
        prResultImageInfo.result_ori_x = prResult.ori_x;
        prResultImageInfo.result_ori_y = prResult.ori_y;

        prResultImageInfo.radius = circle2D1.Get().Radius();

    }catch (const atl::Error& error) {
        qWarning("Throw Error: %s", error.Message());
        return false;
    }
}
